/* GanttProject is an opensource project management tool. Copyright (C) 2011 GanttProject Team This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package net.sourceforge.ganttproject; import java.awt.event.MouseEvent; import java.util.Collections; import java.util.List; import javax.swing.Action; import javax.swing.DefaultCellEditor; import javax.swing.InputMap; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.KeyStroke; import javax.swing.tree.TreeNode; import javax.swing.tree.TreePath; import net.sourceforge.ganttproject.chart.Chart; import net.sourceforge.ganttproject.gui.UIFacade; import net.sourceforge.ganttproject.language.GanttLanguage; import net.sourceforge.ganttproject.resource.AssignmentNode; import net.sourceforge.ganttproject.resource.HumanResource; import net.sourceforge.ganttproject.resource.ResourceNode; import net.sourceforge.ganttproject.roles.RoleManager; import net.sourceforge.ganttproject.roles.RoleManager.RoleEvent; import net.sourceforge.ganttproject.task.ResourceAssignment; import net.sourceforge.ganttproject.task.Task; import net.sourceforge.ganttproject.task.TaskContainmentHierarchyFacade; import org.jdesktop.swingx.table.TableColumnExt; import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode; import org.jdesktop.swingx.treetable.TreeTableNode; import biz.ganttproject.core.table.ColumnList.Column; import com.google.common.base.Joiner; import com.google.common.collect.Lists; public class ResourceTreeTable extends GPTreeTableBase { private final RoleManager myRoleManager; private final ResourceTreeTableModel myResourceTreeModel; private final UIFacade myUiFacade; public ResourceTreeTable(IGanttProject project, ResourceTreeTableModel model, UIFacade uiFacade) { super(project, uiFacade, project.getResourceCustomPropertyManager(), model); myUiFacade = uiFacade; myRoleManager = project.getRoleManager(); myRoleManager.addRoleListener(new RoleManager.Listener() { @Override public void rolesChanged(RoleEvent e) { setEditor(getTableHeaderUiFacade().findColumnByID(ResourceDefaultColumn.ROLE.getStub().getID())); setEditor(getTableHeaderUiFacade().findColumnByID(ResourceDefaultColumn.ROLE_IN_TASK.getStub().getID())); } private void setEditor(ColumnImpl column) { if (column == null || column.getTableColumnExt() == null) { return; } JComboBox comboBox = new JComboBox(getRoleManager().getEnabledRoles()); comboBox.setEditable(false); column.getTableColumnExt().setCellEditor(new DefaultCellEditor(comboBox)); } }); myResourceTreeModel = model; getTableHeaderUiFacade().createDefaultColumns(ResourceDefaultColumn.getColumnStubs()); setTreeTableModel(model); myResourceTreeModel.setSelectionModel(getTreeSelectionModel()); } @Override public String getToolTipText(MouseEvent event) { int column = columnAtPoint(event.getPoint()); if (column >= 0 && isHierarchical(column)) { TreePath pathAtPoint = getTreeTable().getPathForLocation(event.getX(), event.getY()); TreeTableNode nodeAtPoint = pathAtPoint == null ? null : (TreeTableNode) pathAtPoint.getLastPathComponent(); if (nodeAtPoint instanceof AssignmentNode) { Task task = ((AssignmentNode)nodeAtPoint).getTask(); return "<html><body>" + buildPath(task) + "</body></html>"; } } return super.getToolTipText(event); } private String buildPath(Task task) { List<String> names = Lists.newArrayList(); TaskContainmentHierarchyFacade hierarchy = task.getManager().getTaskHierarchy(); for (Task t = task; t != task.getManager().getRootTask(); t = hierarchy.getContainer(t)) { names.add(t.getName()); } Collections.reverse(names); return Joiner.on(GanttLanguage.getInstance().getText("resourceTable.tooltip.joiner")).join(names); } public boolean isVisible(DefaultMutableTreeTableNode node) { return getTreeTable().isVisible(TreeUtil.createPath(node)); } @Override protected List<Column> getDefaultColumns() { return ResourceDefaultColumn.getColumnStubs(); } @Override protected Chart getChart() { return myUiFacade.getResourceChart(); } /** Initialize the treetable. Addition of various listeners, tree's icons. */ @Override protected void doInit() { super.doInit(); myResourceTreeModel.updateResources(); getVerticalScrollBar().addAdjustmentListener(new VscrollAdjustmentListener(myUiFacade.getResourceChart(), false)); } @Override protected void onProjectOpened() { super.onProjectOpened(); myResourceTreeModel.updateResources(); } private RoleManager getRoleManager() { return myRoleManager; } @Override protected TableColumnExt newTableColumnExt(int modelIndex) { TableColumnExt tableColumn = super.newTableColumnExt(modelIndex); if (modelIndex == ResourceDefaultColumn.ROLE.ordinal() || modelIndex == ResourceDefaultColumn.ROLE_IN_TASK.ordinal()) { JComboBox comboBox = new JComboBox(getRoleManager().getEnabledRoles()); comboBox.setEditable(false); tableColumn.setCellEditor(new DefaultCellEditor(comboBox)); } return tableColumn; } /** @return the list of the selected nodes. */ @Deprecated public DefaultMutableTreeTableNode[] getSelectedNodes() { TreePath[] currentSelection = getTreeSelectionModel().getSelectionPaths(); if (currentSelection == null || currentSelection.length == 0) { return new DefaultMutableTreeTableNode[0]; } DefaultMutableTreeTableNode[] dmtnselected = new DefaultMutableTreeTableNode[currentSelection.length]; for (int i = 0; i < currentSelection.length; i++) { dmtnselected[i] = (DefaultMutableTreeTableNode) currentSelection[i].getLastPathComponent(); } return dmtnselected; } public boolean isExpanded(HumanResource hr) { ResourceNode node = ((ResourceTreeTableModel) getTreeTableModel()).getNodeForResource(hr); if (node != null) { return getTreeTable().isExpanded(TreeUtil.createPath(node)); } return false; } public boolean canMoveSelectionUp() { final DefaultMutableTreeTableNode[] selectedNodes = getSelectedNodes(); if (selectedNodes.length != 1) { return false; } DefaultMutableTreeTableNode selectedNode = selectedNodes[0]; TreeNode previousSibling = TreeUtil.getPrevSibling(selectedNode); if (previousSibling == null) { return false; } return true; } /** Move selected resource up */ public void upResource() { final DefaultMutableTreeTableNode[] selectedNodes = getSelectedNodes(); if (selectedNodes.length != 1) { return; } DefaultMutableTreeTableNode selectedNode = selectedNodes[0]; TreeNode previousSibling = TreeUtil.getPrevSibling(selectedNode); if (previousSibling == null) { return; } if (selectedNode instanceof ResourceNode) { HumanResource people = (HumanResource) selectedNode.getUserObject(); myResourceTreeModel.moveUp(people); getTreeSelectionModel().setSelectionPath(TreeUtil.createPath(selectedNode)); } else if (selectedNode instanceof AssignmentNode) { swapAssignents((AssignmentNode) selectedNode, (AssignmentNode) previousSibling); } } public boolean canMoveSelectionDown() { final DefaultMutableTreeTableNode[] selectedNodes = getSelectedNodes(); if (selectedNodes.length != 1) { return false; } DefaultMutableTreeTableNode selectedNode = selectedNodes[0]; TreeNode nextSibling = TreeUtil.getNextSibling(selectedNode); if (nextSibling == null) { return false; } return true; } /** Move the selected resource down */ public void downResource() { final DefaultMutableTreeTableNode[] selectedNodes = getSelectedNodes(); if (selectedNodes.length == 0) { return; } DefaultMutableTreeTableNode selectedNode = selectedNodes[0]; TreeNode nextSibling = TreeUtil.getNextSibling(selectedNode); if (nextSibling == null) { return; } if (selectedNode instanceof ResourceNode) { HumanResource people = (HumanResource) selectedNode.getUserObject(); myResourceTreeModel.moveDown(people); getTreeSelectionModel().setSelectionPath(TreeUtil.createPath(selectedNode)); } else if (selectedNode instanceof AssignmentNode) { swapAssignents((AssignmentNode) selectedNode, (AssignmentNode) nextSibling); } } void swapAssignents(AssignmentNode selected, AssignmentNode sibling) { ResourceAssignment selectedAssignment = selected.getAssignment(); ResourceAssignment previousAssignment = sibling.getAssignment(); selectedAssignment.getResource().swapAssignments(selectedAssignment, previousAssignment); } }